/*
   Copyright (c) 2005 Lucas Mello Schnorr <schnorr@gmail.com>
   
   This file is part of DIMVisual.
   
   DIMVisual is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at your
   option) any later version.
   
   DIMVisual is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   for more details.
   
   You should have received a copy of the GNU Lesser General Public License
   along with DIMVisual; if not, write to the Free Software Foundation, Inc.,
   59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include "MPIRASTROConverter.h"

static NSMutableDictionary *launch;

@implementation MPIRASTROConverter (MPI2)
- (id) convertEventMPI2: (GEvent *) event
{
	NSMutableArray *ret = nil;
	NSString *container;

	if (launch == nil){
		launch = [[NSMutableDictionary alloc] init];
	}

	GFields *f = [event fields];

	NSString *machine, *thread, *node, *identifier, *time;
	NSString *int32AtIndex0, *int32AtIndex1, *int32AtIndex2;
	NSString *stringAtIndex0;

        machine = [[f fieldWithSimpleStringKey:@"machine"] description];
        thread = [[f fieldWithSimpleStringKey: @"thread"] description];
        node = [[f fieldWithSimpleStringKey: @"node"] description];
        identifier = [[event identifier] description];
        time = [[event timestamp] description];
        int32AtIndex0 = [[f fieldWithSimpleStringKey: @"uint32-0"] description];
        int32AtIndex1 = [[f fieldWithSimpleStringKey: @"uint32-1"] description];
        int32AtIndex2 = [[f fieldWithSimpleStringKey: @"uint32-2"] description];
        stringAtIndex0 = [[f fieldWithSimpleStringKey: @"string-0"]description];


	
	ret = [[NSMutableArray alloc] init];

	container = [provider identifierForEntity: 
		[NSArray arrayWithObjects: @"Machine", @"Thread", nil]
				ids:
		[NSArray arrayWithObjects: machine, thread, nil]];

	if (container == nil){
		[ret release];
		return nil;
	}
	
	int etype = atoi ([identifier cString]);

/*******************************************************************************
 		 MPI_BCAST
*******************************************************************************/
	if (etype == MPI_COMM_SPAWN_IN){
		static int lkey = 0;
		//NSString *root = int32AtIndex0;
		NSString *number = int32AtIndex1;
		NSString *name = stringAtIndex0;

//		NSLog (@"root = %@, number = %@, name = %@", root,
//				number, name);
		int i, lnumber;
		lnumber = atoi ([number cString]);
		NSMutableSet *spawn = [[NSMutableSet alloc] init];
		
		for (i = 0; i < lnumber; i++){
			NSString *key = [NSString stringWithFormat: @"s%d", lkey];
			[spawn addObject: key];

			PajeStartLink *sl;
			sl = [[PajeStartLink alloc] init];
			[sl setTime: time];
			[sl setContainer: [provider identifierForEntity: [NSArray arrayWithObjects: @"0", nil] ids: [NSArray arrayWithObjects: @"0", nil]]];
			[sl setSourceContainer: container];
			[sl setEntityType: [provider aliasToName:@"MPICommunication"]];
			[sl setValue: [provider aliasToName: @"MPI_Comm_spawn"]];
			[sl setKey: key];
			[ret addObject: sl];
			[sl release];
			lkey++;
		}
		[launch setObject: spawn forKey: name];
		[ret addObject: [self addPajeSetState: @"MPI_COMM_SPAWN" time: time container: container]];
		

//		PajeNewEvent *ev;
//		ev = [[PajeNewEvent alloc] initWithTime: time];
//		[ev setContainer: container];
//		[ev setEntityType: [provider aliasToName: @"Events"]];
//		[ev setValue: [NSString stringWithFormat: @"MPI_Bcast %d bytes", count]];
//		[ret addObject: ev];
//		[ev release];
		
//		[bcast memberEntering: container
//			andEventNode: node
//			andEventTime: time
//			andRootNode: int32AtIndex1
//			andCommSize: [event int32AtIndex: 2]];
//		[ret addObject: [self addPajeSetState: @"MPI_BCAST" time: time container: container]];
		
	}else if (etype == MPI_COMM_SPAWN_OUT){
//		[ret addObjectsFromArray: [bcast memberExiting: container andEventTime: time andOperationName: @"bcast" andProvider: provider]];
//		[ret addObject: [self addPajeSetState: @"running" time: time container: container]];
	}else if (etype == MPI_INIT){
		[ret addObjectsFromArray: [provider createContainerForEntity:
			[NSArray arrayWithObjects: @"Machine", @"Thread", nil]
			ids:
			[NSArray arrayWithObjects: machine, thread, nil]
			time: time]];
		[ret addObject: [self addPajeSetState: @"running" time: time container: container]];


		PajeNewEvent *ev;
		ev = [[PajeNewEvent alloc] initWithTime: time];
		[ev setContainer: container];
		[ev setEntityType: [provider aliasToName: @"Events"]];
		[ev setValue: [NSString stringWithFormat: @"MPI_Init (%@)", stringAtIndex0]];
		[ret addObject: ev];
		[ev release];


		if ([launch objectForKey: stringAtIndex0] != nil){
			
			NSMutableSet *set = [launch objectForKey: stringAtIndex0];
			NSMutableArray *ar = [[NSMutableArray alloc] init];
			[ar addObjectsFromArray: [set allObjects]];
			NSString *key = [ar objectAtIndex: 0];
			[key retain];
			[ar removeObjectAtIndex: 0];
			NSMutableSet *set2 = [[NSMutableSet alloc] init];
			[set2 addObjectsFromArray: ar];
			[set intersectSet: set2];
			
			PajeEndLink *el;
			el = [[PajeEndLink alloc] init];
			[el setTime: time];
			[el setContainer: [provider identifierForEntity: [NSArray arrayWithObjects: @"0", nil] ids: [NSArray arrayWithObjects: @"0", nil]]];
			[el setDestContainer: container];
			[el setEntityType: [provider aliasToName:@"MPICommunication"]];
			[el setValue: [provider aliasToName: @"MPI_Comm_spawn"]];
			[el setKey: key];
			[ret addObject: el];
			[el release];
		}
		
		
		
	}else if (etype == MPI_FINALIZE){
		PajeNewEvent *ev;
		ev = [[PajeNewEvent alloc] initWithTime: time];
		[ev setContainer: container];
		[ev setEntityType: [provider aliasToName: @"Events"]];
		[ev setValue: [NSString stringWithFormat: @"MPI_Finalize"]];
		[ret addObject: ev];
		[ev release];

		PajeDestroyContainer *dc;
		dc = [[PajeDestroyContainer alloc] initWithTime: time];
		[dc setContainer: container];
		[dc setType: [provider aliasToName: @"Thread"]];
		[ret addObject: dc];
		[dc release];
	}

	[ret autorelease];
	return ret;
}
@end
